package com.afdor.rws.event.driven.channel.transaction.impl;

import com.afdor.rws.event.driven.channel.ChannelProvider;
import com.afdor.rws.event.driven.channel.transaction.ChannelTransactionItem;
import com.afdor.rws.event.driven.entities.Event;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * 默认执行通道事物管理模式
 *
 * @author 悭梵
 * @date Created in 2018-12-17 16:32
 */
public class DefaultChannelTransactionItemImpl implements ChannelTransactionItem {

    @Getter
    private final ChannelProvider channelProvider;

    @Getter
    @Setter
    private String channelTransactionId;

    @Getter
    private volatile List<Event> eventList;

    public DefaultChannelTransactionItemImpl(final String channelTransactionId, final ChannelProvider channelProvider) {
        this.channelProvider = channelProvider;
        // 获取配置的Id生成策略
        this.channelTransactionId = channelTransactionId;
    }

    @Override
    public synchronized void addEvent(Event event) {
        if (this.eventList == null) {
            this.eventList = new ArrayList<>(10);
        }
        this.eventList.add(event);
        event.setStatus(Event.Status.JOIN_TRANSACTION_EVENT_BUS);
    }

    @Override
    public boolean hasEvent() {
        List<Event> eventList = getEventList();
        return !(eventList == null || eventList.isEmpty());
    }

    @Override
    public synchronized void rollback() {
        Optional.ofNullable(getEventList())
                .orElse(Collections.emptyList())
                .forEach(event -> event.setStatus(Event.Status.ROLLEDBACK_EVENT_BUS));
    }

    @Override
    public synchronized boolean commit() {
        Optional.ofNullable(getEventList())
                .orElse(Collections.emptyList())
                .forEach(event -> {
                    getChannelProvider().sendAsyncEvent(event);
                    event.setStatus(Event.Status.COMMITTED_EVENT_BUS);
                });
        return Boolean.TRUE;
    }

}
